using Core;
using System.Collections.Generic;
namespace Model
{
    public class FixedContainer : Entity
    {
        const int max = 999;
        Cell[] cells;

        public Item this[int index]
        {
            get => cells[index].item;
        }

        public int Size => cells.Length;

        public FixedContainer(int size)
        {
            cells = new Cell[size];
            for (int i=0;i<size;i++)
            {
                cells[i] = Create<Cell>();
            }
        }

        public void LockCell(int index)
        {
            if (cells[index].GetComponent<LockComponent>() != null)
                return;
            cells[index].AddComponent<LockComponent>();
        }

        public bool IsLockCell(int index)
        {
            return cells[index].GetComponent<LockComponent>() != null;
        }

        public void UnLock(int index)
        {
            cells[index].RemoveComponent<LockComponent>();
        }

        public bool AddItem(Item entity)
        {
            var emptyIndex = GetEmpty();
            if (emptyIndex == -1)
                return false;
            if(entity.GetComponent<NotStackComponent>() != null)
            {
                cells[emptyIndex].item = entity;
                return true;
            }
            var itemCount = entity.Count;
            var indexs = GetEqualTypes(entity);
            foreach (var index in indexs)
            {
                var c = max - cells[index].item.Count;
                if (c >= itemCount)
                {
                    cells[index].item.Count += itemCount;
                    itemCount = 0;
                    break;
                }
                else
                {
                    itemCount -= c;
                }
            }
            if (itemCount > 0)
            {
                entity.Count = itemCount;
                cells[emptyIndex].item = entity;
            }
            
            return true;
        }

        public bool Insert(int index, Item item)
        {
            if (cells[index].item != null)
                return false;
            cells[index].item = item;
            return true;
        }

        public void MoveTo(int index,int newIndex,int count=-1)
        {
            if(cells[newIndex].IsEmpty){
                cells[newIndex].item = cells[index].item;
                cells[index].item = null;
                return;
            }
            var item = cells[index].item;
            var newItem =cells[newIndex].item;
            if(item.Type != newItem.Type){
                cells[index].item = newItem;
                cells[newIndex].item = item;
                return;
            }
            if(count == -1)
            {
                count = item.Count;
            }
            var c = max - newItem.Count;
            if(c >= count)
            {
                newItem.Count += count;
                cells[index].item = null;
            }
            else
            {
                newItem.Count = max;
                cells[index].item.Count -= c;
            }
        }

        public bool Remove(int index,int count)
        {
            if (index >= cells.Length || cells[index] == null)
                return false;
            var item = cells[index].item;
            if (item.Count < count)
                return false;

            item.Count -= count;
            if (item.Count == 0)
                cells[index].item = null;
            return true;
        }

        int [] GetEqualTypes(Item entity)
        {
            int type = entity.Type;
            List<int> result = new List<int>(cells.Length);
            for (var i=0;i< cells.Length;i++)
            {
                if(!cells[i].IsEmpty && cells[i].item.Type == type)
                {
                    result.Add(i);
                }
            }
            return result.ToArray();
        }

        public int GetEmpty()
        {
            for (var i=0;i< cells.Length;i++)
            {
                if (!IsLockCell(i) && cells[i].IsEmpty)
                    return i;
            }
            return -1;
        }
    }
}
